package com.twxm.breed.service;

import com.twxm.breed.entity.FishPond;
import com.twxm.breed.iot.TimeWheel;
import com.twxm.breed.iot.TimerTask;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Service
public class TimerManager {
    private long currentTick; // 当前刻度

    private ScheduledExecutorService executor; // 定时任务执行器
    public TimerManager(){
        this.executor = Executors.newSingleThreadScheduledExecutor();
        currentTick = System.currentTimeMillis() / 1000 - 1;
        start();
    }

    //
    private Map<Long, TimeWheel> tasksMap = new ConcurrentHashMap<>();

    // 任务对应的时间戳的字典
    private Map<String, Long> taskToSecondsMap = new ConcurrentHashMap<>();

    public void addTask(FishPond fishPond, long delay, long period) {
        // firstDoTask 和 period 都是毫秒时间戳
        long firstDoTaskSeconds = delay / 1000 + currentTick;
        TimeWheel tasks = tasksMap.computeIfAbsent(firstDoTaskSeconds, k -> new TimeWheel());
        TimerTask timerTask = new TimerTask(fishPond, period);
        taskToSecondsMap.put(fishPond.getPondId(), firstDoTaskSeconds);
        tasks.addTask(timerTask);
    }

    public void addTask(TimerTask timerTask){
        long doTaskSeconds = currentTick + timerTask.getPeriod() / 1000;
        taskToSecondsMap.put(timerTask.getFishPondId(), doTaskSeconds);
        TimeWheel tasks = tasksMap.computeIfAbsent(doTaskSeconds, k -> new TimeWheel());
        tasks.addTask(timerTask);
    }

    public void removeTask(String pondId) {
        Long t = taskToSecondsMap.get(pondId);
        if (t == null) {
            return;
        }
        TimeWheel timeWheel = tasksMap.get(t);
        if (timeWheel != null) {
            timeWheel.removeTask(pondId);
            taskToSecondsMap.remove(pondId);
        }

    }


    private void start() {
        executor.scheduleAtFixedRate(() -> {
            TimeWheel wheel = tasksMap.get(currentTick); // 获取当前刻度上的所有任务
            if(wheel == null){
                currentTick ++; // 更新当前刻度
                return;
            }
            ArrayList<TimerTask> onceTasks = new ArrayList<>();
            ArrayList<TimerTask> multiTasks = new ArrayList<>();
            if(wheel.runTasks(onceTasks, multiTasks)){
                // 不用循环执行的任务，可以清理数据了
                for (TimerTask task :
                        onceTasks) {
                    taskToSecondsMap.remove(task.getFishPondId());
                }
                // 循环执行的任务，重新添加一次
                for (TimerTask task :
                        multiTasks) {
                    addTask(task);
                }
            }
            tasksMap.remove(currentTick);// 清空当前刻度上的任务
            currentTick ++; // 更新当前刻度
        }, 1, 1, TimeUnit.SECONDS);
    }

    public void stop() {
        executor.shutdown();
    }

}
